﻿//========================================================= 
/**@file H003UpdateHelper.h
 * @brief H003固件升级工具
 * 
 * @date 2017-02-01   18:43:42
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_H003UPDATEHELPER_H_
#define _LIBZHOUYB_H003UPDATEHELPER_H_
//--------------------------------------------------------- 
#include "../DevUpdaterConvert.h"
#include "../../lc/lc_lib.h"

#include "../../../extension/ability/logger/FolderLogger.h"
using zhou_yb::extension::ability::FolderHelper;

#include "../../../json/json_extractor.h"
using zhou_yb::json_extractor::JsonArgParser;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace application {
namespace updater {
//--------------------------------------------------------- 
class H003UpdateHelper
{
protected:
    H003UpdateHelper() {}
public:
    //----------------------------------------------------- 
    /**
     * @brief 获取当前日期的简短格式
     * @date 2017-02-06 09:20
     * 
     * @param [out] currentDate 获取到的当前日期
     */
    static void GetTrimDate(ByteBuilder& currentDate)
    {
        ByteBuilder date(16);
        get_current_systime(date);
        StringConvert::Remove(date, '-');
        StringConvert::Remove(date, ' ');
        StringConvert::Remove(date, ':');

        currentDate += date;
    }
    /**
     * @brief 更新设备中的版本信息
     * @date 2017-02-06 09:22
     * 
     * @param [in] dev 需要操作的设备
     * @param [in] date [default:CurrentDate] 需要写入的版本日期
     * @param [in] updateDate [default:CurrentDate] 需要写入的升级日期
     * @param [in] version [default:1.0.0.0] 升级后的固件版本信息
     */
    static bool UpdateDevice(IInteractiveTrans& dev, const char* date, const char* updateDate, const char* version)
    {
        WeakRef<IInteractiveTrans> weakRef(dev);
        LC_ComToCCID_CmdAdapter lcCmdAdapter;
        LC_ReaderDevAdapter lcAdapter;

        lcCmdAdapter.SelectDevice(weakRef);
        lcAdapter.SelectDevice(lcCmdAdapter);

        ByteBuilder currentDate(16);
        GetTrimDate(currentDate);

        string sDate = _is_empty_or_null(date) ? currentDate.GetString() : date;
        string sUpdateDate = _is_empty_or_null(updateDate) ? currentDate.GetString() : updateDate;
        string sVersion = _is_empty_or_null(version) ? "1.0.0.0" : version;

        JsonArgParser parser;
        StringArguments arg;
        arg.Put("Date", sDate);
        arg.Put("UpdateDate", sUpdateDate);
        arg.Put("Version", sVersion);

        ByteBuilder devVersion(32);
        parser.ToString(arg, devVersion);

        return true;
    }
    /**
     * @brief 扫描设备获取固件版本信息
     * @date 2017-02-01 18:41
     * 
     * @param [out] date Json::Date 固件生成日期
     * @param [out] updateDate Json::UpdateDate 固件升级日期
     * @param [out] version Json::Version 固件版本
     */
    static bool ScanDevice(IInteractiveTrans& dev, ByteBuilder& date, ByteBuilder& updateDate, ByteBuilder& version)
    {
        WeakRef<IInteractiveTrans> weakRef(dev);
        LC_ComToCCID_CmdAdapter lcCmdAdapter;
        LC_ReaderDevAdapter lcAdapter;

        lcCmdAdapter.SelectDevice(weakRef);
        lcAdapter.SelectDevice(lcCmdAdapter);

        ByteBuilder devVersion(32);
        if(!lcAdapter.GetVersion(devVersion))
            return false;

        // 查找第一个 '{'
        size_t index = StringConvert::IndexOf(devVersion, '{');
        // 没有写入 Json 配置信息
        if(index == SIZE_EOF)
            return false;

        JsonArgParser parser;
        StringArguments arg;
        parser.Parse(devVersion.SubArray(index), arg);

        date.Append(arg["Date"].To<string>("").c_str());
        updateDate.Append(arg["UpdateDate"].To<string>("").c_str());
        version.Append(arg["Version"].To<string>("").c_str());;
        return true;
    }
    /**
     * @brief 扫描升级固件文件,获取固件信息(文件中保存为一个Json文件)
     * @date 2017-02-01 18:47
     * 
     * @param [in] path 固件文件路径
     * @param [out] date Json::Date 固件文件日期
     * @param [out] fileDate Json::FileDate 固件文件创建日期
     * @param [out] version Json::Version 固件版本
     */
    static bool ScanDEV(const char* path, ByteBuilder& date, ByteBuilder& fileDate, ByteBuilder& version)
    {
        ifstream fin;
        ByteBuilder tagInfo(32);
        if(!DevUpdaterConvert::OpenDEV(fin, path, &tagInfo))
            return false;
        DevUpdaterConvert::Close(fin);

        // 查找第一个 '{'
        size_t index = StringConvert::IndexOf(tagInfo, '{');
        // 没有写入 Json 配置信息
        if(index == SIZE_EOF)
            return false;

        JsonArgParser parser;
        StringArguments arg;
        parser.Parse(tagInfo.SubArray(index), arg);

        date.Append(arg["Date"].To<string>("").c_str());
        fileDate.Append(arg["FileDate"].To<string>("").c_str());
        version.Append(arg["Version"].To<string>("").c_str());;
        return true;
    }
    //----------------------------------------------------- 
    #ifndef _WIN32
    /// 返回当前Android系统下是否支持U盘升级模式
    static bool IsStorageUpdate(ByteBuilder& path, const char* moduleName)
    {
        const char ROOT_DIR[] = "/dev/";

        list_t<string> otgdirs;
        FolderHelper::EnumAll(ROOT_DIR, &otgdirs, NULL);

        // 检测H003目录
        list_t<string>::iterator itr;
        string sName = _strput(moduleName);

        string dirpath;
        for(itr = otgdirs.begin();itr != otgdirs.end(); ++itr)
        {
            if(!StringConvert::StartWith(itr->c_str(), "uhost", true))
                continue;

            dirpath = ROOT_DIR;
            dirpath += *itr;
            if(sName.length() > 0)
            {
                dirpath += "/";
                dirpath += sName;
            }

            if(FolderHelper::IsFolderExist(dirpath.c_str()))
            {
                if(IsFolderContainsDEV(dirpath.c_str(), path))
                    return true;
            }
        }
        return false;
    }
    /**
     * @brief 检测指定的 Android 文件夹下是否有 dev 文件
     * @date 2017-02-02 12:20
     * 
     * @param [in] dir 需要扫描的文件夹
     * @param [out] path 获取到的第一个dev文件路径
     */
    static bool IsFolderContainsDEV(const char* dir, ByteBuilder& path)
    {
        // 检查目录下dev固件文件属性
        list_t<string> files;
        FolderHelper::EnumFiles(dir, files, NULL, ".dev");

        if(files.size() < 1)
            return false;

        path += dir;
        path += "/";
        path += files.front().c_str();
        return true;
    }
    #endif
    //----------------------------------------------------- 
    /**
     * @brief 将hex文件保存为H003的dev固件升级文件
     * @date 2017-02-02 14:47
     * 
     * @param [in] hex 输入文件路径
     * @param [in] dev 输出文件路径
     * @param [in] date 固件版本日期
     * @param [in] fileDate 文件生成版本日期(NULL则以当前时间生成)
     * @param [in] version 固件版本号
     */
    static bool SaveHEXtoDEV(const char* hex, const char* dev, const char* date, const char* fileDate, const char* version)
    {
        // 生成文件 TAG 信息 
        ByteBuilder tagInfo(32);
        JsonArgParser parser;
        ByteBuilder currentDate(16);
        GetTrimDate(currentDate);

        string sDate = _is_empty_or_null(date) ? currentDate.GetString() : date;
        string sFileDate = _is_empty_or_null(fileDate) ? currentDate.GetString() : fileDate;
        string sVersion = _is_empty_or_null(version) ? "1.0.0.0" : version;

        StringArguments arg;
        arg.Put("Date", sDate);
        arg.Put("FileDate", sFileDate);
        arg.Put("Version", sVersion);

        parser.ToString(arg, tagInfo);
        return DevUpdaterConvert::SaveHEXtoDEV(hex, dev, "", tagInfo);
    }
    //----------------------------------------------------- 
};
//--------------------------------------------------------- 
} // namespace updater
} // namespace application
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_H003UPDATEHELPER_H_
//========================================================= 